package com.nsu.konus.control;

/**
 * @author Strot
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;


public class LocalServer
{
    private Selector selector = null;
    
    private ServerSocketChannel server = null;
    
    private SocketChannel socket = null;
    
    private int port;
    
    private SelectionKey acceptKey;

	public LocalServer(int port)
    {
		this.port = port;
    }

    public void initialize() throws IOException,UnknownHostException
    {
		selector = Selector.open();
		server = ServerSocketChannel.open();
		server.configureBlocking(false);
		InetAddress ia = InetAddress.getByName("127.0.0.1");
		InetSocketAddress isa = new InetSocketAddress(ia, port);
		server.socket().bind(isa);
    }
    
    public void listen() throws ClosedChannelException {
		acceptKey = server.register(selector, SelectionKey.OP_ACCEPT );	
    }
    
    public void accept() throws ClosedChannelException, IOException {
    	
		if (acceptKey.selector().select() > 0)
		{	
			Set readyKeys = selector.selectedKeys();
			Iterator it = readyKeys.iterator();

			while (it.hasNext()) {
				SelectionKey key = (SelectionKey)it.next();
				it.remove();
                
				if (key.isAcceptable()) {
					ServerSocketChannel ssc = (ServerSocketChannel)
						key.channel();
					socket = (SocketChannel) ssc.accept();
					socket.configureBlocking(false);
					socket.register(selector,
						SelectionKey.OP_READ | SelectionKey.OP_WRITE);
					return;
				}
			}
		}
    }
    
    public boolean write(byte[] message) throws IOException {
    	
		if (acceptKey.selector().select() > 0)
		{	
			Set readyKeys = selector.selectedKeys();
			Iterator it = readyKeys.iterator();

			while (it.hasNext()) {
				SelectionKey key = (SelectionKey)it.next();
				it.remove();
                
				if (key.isWritable()) {
					return writeMessage(socket, message);
				}
			}
		}
		return false;
    }
    
    public byte[] read() throws IOException {
		if (acceptKey.selector().select() > 0)
		{	
			Set readyKeys = selector.selectedKeys();
			Iterator it = readyKeys.iterator();

			while (it.hasNext()) {
				SelectionKey key = (SelectionKey)it.next();
				it.remove();
                
				if (key.isReadable()) {
					return readMessage(key);
				}
			}
		}
		return null;
    }
    
    private boolean writeMessage(SocketChannel socket, byte[] message)
    {
		try
		{
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			buffer.put(message);
			buffer.flip();
    
			int nBytes = socket.write(buffer);
			if (nBytes != message.length)
				return false;
			//System.out.println(message);
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return false;
		}
		return true;
    }
  
    private byte[] readMessage(SelectionKey key) throws IOException
    {
		int nBytes = 0;
		socket = (SocketChannel)key.channel();
        ByteBuffer buf = ByteBuffer.allocate(1024);
		//try
		{
            nBytes = socket.read(buf);
			buf.flip();
			byte[] originalMessage = buf.array(); 
			byte[] message = new byte[nBytes];
			for(int i = 0; i < message.length; i++)
				message[i] = originalMessage[i];
			return message;
        }
		//catch(IOException e)
		//return null;
    }
}

